import { _decorator, Component, Node, instantiate, sys, url, Prefab, EventTouch, Label, tween, v2, Vec3 } from 'cc';
import { Tube } from './Tube';
import { BallColor } from './Enums';
import { Ball } from './Ball';
import { WinPanel } from './WinPanel';
import { GuidelineComponent } from './GuidelineComponent';
import { getNewParentLocalPosInChild, getRelativePosition } from './Tool';

const { ccclass, property } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {
    private static instance: GameManager = null;

    // 属性声明
    @property
    totalTubes: number = 4; // 总试管数量
    @property
    filledTubes: number = 2; // 最后需装满小球的试管数量
    @property
    capacity: number = 4; // 每个试管的容量

    @property({ type: [Tube] })
    tubes: Tube[] = []; // 试管数组
    @property({ type: [Ball] })
    selectedBalls: Ball[] = []; // 选中的小球数组

    @property(Node)
    tubesNode: Node = null; // 试管节点
    @property(Prefab)
    tubePrefab: Prefab = null; // 试管预制体
    @property(Prefab)
    ballPrefab: Prefab = null; // 小球预制体
    
    @property(WinPanel)
    winPanel: WinPanel = null; // 胜利面板节点

    // 引导组件
    @property(GuidelineComponent)
    guideline: GuidelineComponent = null;
    @property([Node])
    targets: Node[] = []; // 引导目标节点数组
    @property(String)
    guideTexts : string[] = [
        "点击试管取出小球",
        "点击试管放入小球",
        "所有小球归位则胜利",
        "左上角可自定义关卡",
        "横竖屏切换"
    ];
    private isGuideActive: boolean = true; // 是否启用引导

    private constructor() {
        super();
        // 构造函数私有化，防止外部实例化
    }

    // 获取单例的方法
    public static getInstance(): GameManager {
        if (this.instance === null) {
            this.instance = new GameManager();
        }
        return this.instance;
    }

    start() {
        if (!GameManager.instance) {
            GameManager.instance = this;
        }
        this.initGame();

        this.initGuideTargets().then(() => {
        // 给目标节点添加触摸事件监听器
        this.targets.forEach(target => {
            if (target) {
                target.on(Node.EventType.TOUCH_START, this.onTouchTarget, this);
            }
        });
            setTimeout(() => {
                this.showGuildline(0);
            }, 1000);
        });
    }

    // 初始化游戏方法
    initGame() {
        //this.tubesNode.removeAllChildren();

        if (this.totalTubes <= this.filledTubes) {
            console.error('总试管数量需要大于最后装满小球的试管数量');
            return;
        }

        // 初始化试管
        for (let i = 0; i < this.totalTubes; i++) {
            const tubeNode = instantiate(this.tubePrefab);
            const tube = tubeNode.getComponent(Tube);
            //tube.node.parent = this.node;
            tube.capacity = this.capacity;
            //tube.clearExistingParts();
            tube.initTubeParts();
            tube.node.parent = this.tubesNode; // 将试管添加到指定节点  
            this.tubes.push(tube);
        }
        //console.log(`试管 ${this.tubes.length} 初始化完成`);

        // 初始化小球
        const balls: Ball[] = [];
        const colorEnumValues = (Object as any).values(BallColor).filter((v: any) => typeof v === 'number') as number[];
        const colorBallPrefabMap: Record<number, Node> = {};

        // 先为每种颜色创建一个小球节点并缓存
        for (let colorIndex = 0; colorIndex < this.filledTubes; colorIndex++) {
            const ballNode = instantiate(this.ballPrefab);
            const ball = ballNode.getComponent(Ball);
            ball.ballColor = colorEnumValues[colorIndex];
            colorBallPrefabMap[colorEnumValues[colorIndex]] = ballNode;
        }

        // 再批量克隆
        for (let colorIndex = 0; colorIndex < this.filledTubes; colorIndex++) {
            for (let j = 0; j < this.capacity; j++) {
                // 克隆已缓存的同色小球节点
                const ballNode = instantiate(colorBallPrefabMap[colorEnumValues[colorIndex]]);
                const ball = ballNode.getComponent(Ball);
                ball.ballColor = colorEnumValues[colorIndex];
                balls.push(ball);
            }
        }

        // 依次放入 filledTubes 个试管
        let tubeFillCount = new Array(this.totalTubes).fill(0);
        for (let i = 0; i < balls.length; i++) {
            // 找到所有未满的试管索引
            const availableTubes: number[] = [];
            for (let t = 0; t < this.totalTubes; t++) {
                if (tubeFillCount[t] < this.capacity) {
                    availableTubes.push(t);
                }
            }
            // 随机选一个未满的试管
            const randIdx = Math.floor(Math.random() * availableTubes.length);
            const tubeIdx = availableTubes[randIdx];
            this.tubes[tubeIdx].addBall(balls[i]);
            tubeFillCount[tubeIdx]++;
        }
    }

    // 引导目标节点初始化方法
    private async initGuideTargets() {
        // 等待游戏初始化完成
        await this.waitForGameInit();

        // 目标节点1：不为空的试管
        const nonEmptyTube = this.tubes.find(tube => tube.getBallCount() > 0)?.middleNode;
        if (nonEmptyTube) {
            this.targets[0] = nonEmptyTube;
        }

        // 目标节点2：有存放空间的试管
        let tubeWithSpace = this.tubes.find(tube => tube.getEmptySpace() > 0)?.middleNode;
        // 检查找到的节点是否和 targets[0] 相同，如果相同则重新查找
        while (tubeWithSpace === this.targets[0]) {
            const remainingTubes = this.tubes.filter(tube => tube.middleNode !== this.targets[0]);
            tubeWithSpace = remainingTubes.find(tube => tube.getEmptySpace() > 0)?.middleNode;
            if (!tubeWithSpace) {
                break;
            }
        }
        if (tubeWithSpace) {
            this.targets[1] = tubeWithSpace;
        }

        // 目标节点3、4、5 在场景中已存在
        // 目标节点3 是 guideLabel 节点
        // 目标节点4 是 SettingPanel 节点
        // 目标节点5 是 OrientationButton 节点
    }

    // 等待游戏初始化完成的方法
    private waitForGameInit() {
        return new Promise<void>((resolve) => {
            const checkInit = () => {
                if (this.tubes.length > 0) {
                    resolve();
                } else {
                    setTimeout(checkInit, 100);
                }
            };
            checkInit();
        });
    }

    // 修改显示引导方法
    private showGuildline(index: number) {
        if (index < this.targets.length && this.targets[index]) {
            const target = this.targets[index];
            const text = this.guideTexts[index];
            this.guideline.show(target, text);
        }
    }

    // 触摸目标节点的处理逻辑
    private onTouchTarget(event: EventTouch) {
        if (!this.isGuideActive) return; // 如果引导已结束，直接返回

        const currentTarget = event.currentTarget as Node;
        const index = this.targets.indexOf(currentTarget);
        if (index !== -1) {
            this.guideline.hide();
            const nextIndex = index + 1;
            if (nextIndex < this.targets.length && this.targets[nextIndex]) {
                this.showGuildline(nextIndex);
            } else {
                // 引导结束
                this.isGuideActive = false; // 禁用引导
                console.log('引导结束');
            }
        }
    }

    // 点击试管的处理逻辑
    async onTubeClicked(tube: Tube) {
        if (this.selectedBalls.length === 0 && tube.parts.length > 0) {
        // 情况一：无选中小球且试管内小球不为空
        const balls = tube.removeTopSameColorBalls();
        this.selectedBalls = balls;
        console.log(`选中小球: ${balls.map(ball => ball.ballColor)}`);
        tube.moveBallToMouth(balls);
    } else if (this.selectedBalls.length > 0) {
        const topBall = this.selectedBalls[0];
        if (tube === topBall.tube) {
            // 情况二：点击当前试管，放回原试管（从后往前放回）
            for (let i = this.selectedBalls.length - 1; i >= 0; i--) {
                console.log(`点击当前试管将小球 ${this.selectedBalls[i].ballColor} 放回原试管`);
                tube.addBall(this.selectedBalls[i]);
                this.selectedBalls[i].tube = tube; // 更新小球所属试管
            }
            this.selectedBalls = [];
        } else {
            // 情况三
            // 1. 判断空间是否足够
            let emptyCount = 0;
            for (let i = 0; i < tube.parts.length; i++) {
                if (!tube.parts[i].hasBall()) emptyCount++;
            }
            if (emptyCount < this.selectedBalls.length) {
                // 空间不足，放回原试管
                for (let i = this.selectedBalls.length - 1; i >= 0; i--) {
                    this.selectedBalls[i].tube.addBall(this.selectedBalls[i]);
                }
                // 尝试选中目标试管顶部同色球
                const balls = tube.removeTopSameColorBalls();
                if (balls.length > 0) {
                    this.selectedBalls = balls;
                    tube.moveBallToMouth(balls);
                } else {
                    this.selectedBalls = [];
                }
            } else {
                await tube.addSelectedBalls(this.selectedBalls);
                this.selectedBalls = [];
            }
        }
    }
}

    // 查找是否有其他试管顶部有相同颜色的小球
    findOtherTubeWithSameColor(color: BallColor): Tube | null {
        for (const tube of this.tubes) {
            if (tube !== this.selectedBalls[0].tube && tube.getTopBall() && tube.getTopBall().ballColor === color) {
                return tube;
            }
        }
        return null;
    }
    
    // 检查游戏是否结束
    checkGameOver() {
    let completedCount = 0;
    for (let tube of this.tubes) {
        if (tube.isCompleted) {
            completedCount++;
        }
    }
    if (completedCount === this.filledTubes) {
        this.showWinEffect();
    }
}

    // 显示游戏胜利效果
    showWinEffect() {
        console.log('游戏胜利！');
        // 等待 1 秒后显示 WinCanvas 面板
        this.scheduleOnce(() => {
            this.winPanel.showPanel();
            // 禁用上一个面板的交互
            this.tubesNode.active = false; 
        }, 1);
    }

    // 重新开始游戏方法
    restartGame() {
        this.tubesNode.removeAllChildren();
        this.tubes = [];
        this.selectedBalls = [];

        // 重新初始化游戏
        this.initGame();
        // 启用上一个面板的交互
        this.tubesNode.active = true;
    }

     // 重载关卡方法
    reloadLevel(totalTubes: number, filledTubes: number, tubeCapacity: number) {
        this.tubesNode.removeAllChildren();
        // 清空试管数组和选中小球数组
        this.tubes = [];
        this.selectedBalls = [];

        this.totalTubes = totalTubes;
        this.filledTubes = filledTubes;
        this.capacity = tubeCapacity;
        // 实现根据输入的总试管数量和需装满的试管数量重新初始化关卡的逻辑
        // 示例：
        this.initGame();
    }
}


